package com.xiangxiao.rpan.authority.tree;

import org.apache.commons.collections.CollectionUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.*;

/**
 * @Projectname: TreeUtil
 * @Author: xiangxiao
 * @Email: 573768011@qq.com
 * @Data:2023/3/29 1:03
 */
public class TreeUtil {
  private static final Logger LOG = LogManager.getLogger(TreeUtil.class);

  private TreeUtil() {
  }

  public static String nodeType(Class<?> class1) {
    if (null == class1) {
      return null;
    }
    NodeType nodeType = class1.getAnnotation(NodeType.class);
    if (null == nodeType) {
      return toUnderlineName(class1.getSimpleName());
    }
    return nodeType.value();
  }

  public static int nodeTypeSort(Class<?> class1) {
    if (null == class1) {
      return 0;
    }
    NodeType nodeType = class1.getAnnotation(NodeType.class);
    if (null == nodeType) {
      return 0;
    }
    return nodeType.sort();
  }

  public static Class<? extends TreeNode> previousClass(Class<? extends TreeNode> class1) {
    if (null == class1) {
      return null;
    }
    PreviousClass previouse = class1.getAnnotation(PreviousClass.class);
    return null == previouse ? null : previouse.value();
  }

  public static <T> List<T> convert(Class<T> clazz, List list) {
    if (null == list || null == clazz) {
      return new ArrayList<>();
    }
    List<T> retList = new ArrayList<>();
    for (Object o : list) {
      try {
        retList.add((T) o);
      } catch (Exception e) {
        LOG.warn("Cannot convert " + o + " to " + clazz + ", catch exception: ", e);
      }
    }
    return retList;
  }

  public static Map<Class<? extends TreeNode>, Set<Long>> idMap(Collection<TreeNode> treeNodes) {
    Map<Class<? extends TreeNode>, Set<Long>> retMap = new HashMap<>(16);
    if (CollectionUtils.isEmpty(treeNodes)) {
      return retMap;
    }
    for (TreeNode treeNode : treeNodes) {
      Set<Long> set = retMap.get(treeNode.getClass());
      if (null == set) {
        set = new HashSet<>();
        retMap.put(treeNode.getClass(), set);
      }
      set.add(treeNode.getId());
    }
    return retMap;
  }

  public static boolean hasParent(Long parentId) {
    return null != parentId && !parentId.equals(0L);
  }

  public static boolean hasPrevious(Long previousId) {
    return null != previousId && !previousId.equals(0L);
  }


  /**
   * 查询叶子节点列表（没有权限控制）
   *
   * @param treeNodeList 节点列表
   * @param filterClass  过滤类型
   * @return List<TreeNode> 只有一级
   * @author shixiaohua
   */
  @SuppressWarnings("unchecked")
  public static <T extends TreeNode> List<T> leaf(List<T> treeNodeList, Class<? extends TreeNode> filterClass) {
    List<T> retList = new ArrayList<>();
    if (CollectionUtils.isEmpty(treeNodeList)) {
      return retList;
    }
    for (T node : treeNodeList) {
      if (null == node) {
        continue;
      }
      if (!node.getHasChild() && !node.getHasNext()) {
        if (null == filterClass || filterClass.equals(node.getClass())) {
          retList.add(node);
        }
        continue;
      }
      if (node.getHasChild()) {
        retList.addAll((List<T>) leaf(node.getChildList(), filterClass));
      }
      if (node.getHasNext()) {
        retList.addAll((List<T>) leaf(node.getNextList(), filterClass));
      }
    }
    return retList;
  }


  /**
   * 查询所有子节点列表（没有权限控制）
   *
   * @param treeNodeList 节点列表
   * @param filterClass  过滤类型
   * @return List<TreeNode> 只有一级
   * @author shixiaohua
   */
  @SuppressWarnings("unchecked")
  public static <T extends TreeNode> List<T> child(List<T> treeNodeList, Class<? extends TreeNode> filterClass) {
    List<T> retList = new ArrayList<>();
    if (CollectionUtils.isEmpty(treeNodeList)) {
      return retList;
    }
    for (T node : treeNodeList) {
      if (null == node) {
        continue;
      }
      retList.add(node);
      if (!node.getHasChild() && !node.getHasNext()) {
        if (null == filterClass || filterClass.equals(node.getClass())) {
          retList.add(node);
        }
        continue;
      }
      if (node.getHasChild()) {
        retList.addAll((List<T>) child(node.getChildList(), filterClass));
      }
      if (node.getHasNext()) {
        retList.addAll((List<T>) child(node.getNextList(), filterClass));
      }
    }
    return retList;
  }

  /**
   * 将驼峰转下划线，如："helloWorld"转为"hello_world"
   *
   * @param s
   * @return
   */
  public static String toUnderlineName(String s) {
    if (s == null) {
      return null;
    }

    StringBuilder sb = new StringBuilder();
    boolean upperCase = false;
    for (int i = 0; i < s.length(); i++) {
      char c = s.charAt(i);

      boolean nextUpperCase = true;

      if (i < (s.length() - 1)) {
        nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
      }

      if ((i >= 0) && Character.isUpperCase(c)) {
        boolean isUpperCase = !upperCase || !nextUpperCase;
        if (isUpperCase && i > 0) {
          sb.append("_");
        }
        upperCase = true;
      } else {
        upperCase = false;
      }

      sb.append(Character.toLowerCase(c));
    }

    return sb.toString();
  }

  /**
   * 获取指定节点的父节点链条
   *
   * @param nodeMap
   * @param nodeId
   * @return
   */
  public static List<Long> getParentIdListOfTargetNode(Map<Long, TreeNode> nodeMap, Long nodeId) {
    TreeNode treeNode = nodeMap.get(nodeId);
    List<Long> idList = new ArrayList<>();
    while (treeNode != null) {
      idList.add(treeNode.getId());
      treeNode = nodeMap.get(treeNode.getParentId());
    }

    return idList;
  }

  /**
   * 将节点转成Map,key为节点的id,value为节点对象
   *
   * @param nodeList
   * @return
   */
  public static Map<Long, TreeNode> transformToNodeMap(List<TreeNode> nodeList) {
    Map<Long, TreeNode> nodeMap = new HashMap<>();
    for (TreeNode treeNode : nodeList) {
      nodeMap.put(treeNode.getId(), treeNode);
    }

    return nodeMap;
  }
}
